home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DJGPP / DJSRC111.ZIP / utils / djtarx.c < prev    next >
C/C++ Source or Header  |  1993-10-19  |  7KB  |  337 lines

  1. #include <stdio.h>
  2. #include <fcntl.h>
  3. #include <sys/stat.h>
  4. #include <string.h>
  5. #include <errno.h>
  6. #include <dos.h>
  7. #include <time.h>
  8. #include <io.h>
  9.  
  10. #include "oread.h"
  11.  
  12. void Fatal(char *msg)
  13. {
  14.   fprintf(stderr, "Fatal! %s!\n", msg);
  15.   exit(1);
  16. }
  17.  
  18. /*------------------------------------------------------------------------*/
  19.  
  20. typedef struct CE {
  21.   struct CE *next;
  22.   char *from;
  23.   char *to;
  24. } CE;
  25.  
  26. #define HASHSIZE 2048
  27. #define HASHMASK 2047
  28. #define HASHBITS 11
  29. CE *htab[HASHSIZE];
  30.  
  31. unsigned long hash(unsigned char *cp)
  32. {
  33.   unsigned long rv = 0;
  34.   while (*cp)
  35.     rv += *cp++;
  36.   while (rv > HASHMASK)
  37.     rv = (rv & HASHMASK) + (rv >> HASHBITS);
  38.   return rv;
  39. }
  40.  
  41. void store_entry(char *from, char *to)
  42. {
  43.   unsigned long h = hash(from);
  44.   CE *ce = (CE *)malloc(sizeof(CE));
  45.   if (ce == 0)
  46.     Fatal("Out of memory");
  47.   ce->from = strdup(from);
  48.   ce->to = strdup(to);
  49.   ce->next = htab[h];
  50.   htab[h] = ce;
  51. }
  52.  
  53. char *get_entry(char *from)
  54. {
  55.   CE *ce;
  56.   for (ce = htab[hash(from)]; ce; ce=ce->next)
  57.   {
  58.     if (strcmp(ce->from, from) == 0)
  59.       return ce->to;
  60.   }
  61.   return from;
  62. }
  63.  
  64. void DoNameChanges(char *fname)
  65. {
  66.   FILE *f = fopen(fname, "r");
  67.   char from[100], to[100];
  68.   char line[250];
  69.   if (f == 0)
  70.   {
  71.     perror(fname);
  72.     exit(1);
  73.   }
  74.   while (1)
  75.   {
  76.     fgets(line, 250, f);
  77.     if (feof(f))
  78.       break;
  79.     to[0] = 0;
  80.     sscanf(line, "%s %s", from, to);
  81.     if (to[0])
  82.       store_entry(from, to);
  83.   }
  84.   fclose(f);
  85. }
  86.  
  87. /*------------------------------------------------------------------------*/
  88.  
  89. FILE *change_file;
  90.  
  91. int v_switch = 0;
  92.  
  93. main(int argc, char **argv)
  94. {
  95.   int i = 1;
  96.   if (argc < 2)
  97.   {
  98.     fprintf(stderr, "djtarx [-n changeFile] [-v] tarfile . . .\n");
  99.     exit(1);
  100.   }
  101.   while ((argc > i) && (argv[i][0] == '-'))
  102.   {
  103.     switch (argv[i][1])
  104.     {
  105.       case 'n':
  106.         DoNameChanges(argv[i+1]);
  107.         i++;
  108.         break;
  109.       case 'v':
  110.         v_switch = 1;
  111.         break;
  112.     }
  113.     i++;
  114.   }
  115.   for (; i < argc; i++)
  116.     tarread(argv[i]);
  117.   change_file = fopen("/tarchange.lst", "w");
  118.   dump_changes();
  119.   fclose(change_file);
  120. }
  121.  
  122. /*------------------------------------------------------------------------*/
  123.  
  124. typedef struct CHANGE {
  125.   struct CHANGE *next;
  126.   char *old;
  127.   char *new;
  128.   int isdir; /* 0=file, 1=dir, 2=skip */
  129. } CHANGE;
  130.  
  131. CHANGE *change_root = 0;
  132.  
  133. dump_changes()
  134. {
  135.   CHANGE *c;
  136.   for (c=change_root; c; c=c->next)
  137.     fprintf(change_file, "%s -> %s\n", c->old, c->new);
  138. }
  139.  
  140. int change(char *fname, char *problem, int isadir)
  141. {
  142.   CHANGE *ch;
  143.   char new[200];
  144.   char *pos, *info;
  145.  
  146.   for (ch=change_root; ch; ch = ch->next)
  147.     if ((strncmp(fname, ch->old, strlen(ch->old)) == 0) && ch->isdir)
  148.     {
  149.       if (ch->isdir == 2)
  150.       {
  151.         printf("  [ skipping %s ]\n", fname);
  152.         return 0;
  153.       }
  154. /*      printf("  [ changing %s to ", fname); */
  155.       sprintf(new, "%s%s", ch->new, fname+strlen(ch->old));
  156.       strcpy(fname, new);
  157. /*      printf("%s ]\n", fname); */
  158.       return 1;
  159.     }
  160.   info = strstr(fname, ".info-");
  161.   if (info)
  162.   {
  163.     strcpy(new, fname);
  164.     info = strstr(new, ".info-");
  165.     strcpy(info+2, info+6);
  166.     printf("[ changing %s to %s ]\n", fname, new);
  167.   }
  168.   else
  169.   {
  170.     char *plus = strstr(fname, "++"), *plus2;
  171.     if (plus)
  172.     {
  173.       strcpy(new, fname);
  174.       plus2 = strstr(new, "++");
  175.       strcpy(plus2, "plus");
  176.       strcpy(plus2+4, plus+2);
  177.     }
  178.     else
  179.     {
  180.       printf("  %s %s\n  new name : ", problem, fname);
  181.       gets(new);
  182.     }
  183.   }
  184.   if ((strcmp(new, "") == 0) && (isadir == 2))
  185.     return 0;
  186.   if (isadir) isadir=1;
  187.   ch = (CHANGE *)malloc(sizeof(CHANGE));
  188.   if (ch == 0)
  189.     Fatal("Out of memory");
  190.   ch->next = change_root;
  191.   change_root = ch;
  192.   ch->old = strdup(fname);
  193.   pos = strrchr(fname, '/');
  194.   if (pos && (strchr(new, '/') == 0))
  195.   {
  196.     ch->new = (char *)malloc(strlen(new) + (pos-fname) + 2);
  197.     if (ch->new == 0)
  198.       Fatal("Out of memory");
  199.     *pos = 0;
  200.     sprintf(ch->new, "%s/%s", fname, new);
  201.   }
  202.   else
  203.     ch->new = strdup(new);
  204.   ch->isdir = isadir;
  205.   strcpy(fname, ch->new);
  206.   if (new[0] == 0)
  207.   {
  208.     ch->isdir = 2;
  209.     return 0;
  210.   }
  211.   return 1;
  212. }
  213.  
  214. /*------------------------------------------------------------------------*/
  215.  
  216. typedef struct {
  217.   char name[100];
  218.   char operm[8];
  219.   char ouid[8];
  220.   char ogid[8];
  221.   char osize[11];
  222.   char otime[12];
  223.   char ocsum[8];
  224.   char flags[1];
  225.   char filler[356];
  226. } TARREC;
  227.  
  228. char buf[512];
  229.  
  230. tarread(char *fname)
  231. {
  232.   TARREC header;
  233.   int r;
  234.   void *f;
  235.   long perm, uid, gid, size, ftime, csum;
  236.   int dsize;
  237.   char *changed_name;
  238.   long posn=0;
  239.   struct tm tm;
  240.  
  241.   f = oread_open(fname);
  242.  
  243.   while (1)
  244.   {
  245.     oread_read(f, &header);
  246.     if (header.name[0] == 0)
  247.       break;
  248.     sscanf(header.operm, "%lo", &perm);
  249.     sscanf(header.ouid, "%lo", &uid);
  250.     sscanf(header.ogid, "%lo", &gid);
  251.     sscanf(header.osize, "%lo", &size);
  252.     sscanf(header.otime, "%lo", &ftime);
  253.     changed_name = get_entry(header.name);
  254.     if (v_switch)
  255.       printf("%08lx %6lo ", posn, perm);
  256.     else
  257.       printf("%c%c%c%c ",
  258.              perm & 040000 ? 'd' : '-',
  259.              perm & 000400 ? 'r' : '-',
  260.              perm & 000200 ? 'w' : '-',
  261.              perm & 000100 ? 'x' : '-');
  262.     printf("%.20s %9ld %s", ctime(&ftime)+4, size, changed_name);
  263.     if (header.flags[1] == 0x32)
  264.       printf(" -> %s", header.filler);
  265.     printf("\n");
  266.     posn += 512 + (size+511) & ~511;
  267. /*    printf("%6lo %02x %12ld %s\n", perm, header.flags[0], size, changed_name); */
  268.     if (changed_name[strlen(changed_name)-1] == '/')
  269.     {
  270.       changed_name[strlen(changed_name)-1] = 0;
  271.       do {
  272.         r = mkdir(changed_name
  273. #ifdef __GO32__
  274.     ,0
  275. #endif
  276.         );
  277.         if (r && (errno==EACCES))
  278.         {
  279.           change(changed_name, "Duplicate directory name", 2);
  280.           continue;
  281.         }
  282.         if (r)
  283.           r = change(changed_name, "Unable to create directory", 1);
  284.         else
  285.           printf("Making directory %s\n", changed_name);
  286.       } while (r);
  287.     }
  288.     else
  289.     {
  290.     open_file:
  291.       r = open(changed_name, O_WRONLY|O_BINARY|O_CREAT|O_EXCL,
  292.         S_IWRITE|S_IREAD);
  293.       if (r < 0)
  294.         if (change(changed_name, "Cannot exclusively open file", 0))
  295.           goto open_file;
  296.         else
  297.         {
  298.           oread_skip(f, (size+511) & ~511);
  299.         }
  300.       else
  301.       {
  302.         long ftv;
  303.         struct ftime ftimes;
  304.         struct tm *tm;
  305.         while (size)
  306.         {
  307.           if (size < 512)
  308.             dsize = size;
  309.           else
  310.             dsize = 512;
  311.           oread_read(f, buf);
  312.           if (write(r, buf, dsize) < dsize)
  313.           {
  314.             printf("Out of disk space\n");
  315.             exit(1);
  316.           }
  317.           size -= dsize;
  318.         }
  319.         close(r);
  320.         r = open(changed_name, O_RDONLY);
  321.         tm = localtime(&ftime);
  322.         ftimes.ft_tsec = tm->tm_sec / 2;
  323.         ftimes.ft_min = tm->tm_min;
  324.         ftimes.ft_hour = tm->tm_hour;
  325.         ftimes.ft_day = tm->tm_mday;
  326.         ftimes.ft_month = tm->tm_mon+1;
  327.         ftimes.ft_year = tm->tm_year - 80;
  328.         setftime(r, &ftimes);
  329.         close(r);
  330.         if (!(perm & 0200))
  331.           _chmod(changed_name, 1, FA_RDONLY);
  332.       }
  333.     }
  334.   }
  335.   oread_close(f);
  336. }
  337.